<?php
  include "counter.php";
  if (!$days = $counter->get_input('days', 'number', 'get')) {
      $days = 60;
  }
?>
<HTML>
<?php pagehead("Machine uptimes") ?>
<BODY>
<?php pagetop() ?>
<h1><img src="../gifs/Logo-small.png">
Machine uptimes</h1>
The data below is based on the currently available data from the <a
href="/scripts/">machine-update scripts</a> that are run by a lot of
machines.
<p>
Only data from machines that have updated within the last
<?php echo $days ?> days is included.
<?php
  function presentquery($query, $total=-1, $limit=1) {
      global $days;
      while ($arr = mysql_fetch_row($query)) {
          if ($arr[0] <= $limit) {
              $leftovers += $limit;
              continue;
          }
          echo '          <tr>'."\n";
          for ($ix=0; $ix < mysql_num_fields($query); $ix++) {
              $typ = mysql_field_type($query, $ix);
              if ($typ == "string") {
                  echo '              <td>'. htmlspecialchars($arr[$ix]);
              } elseif ($typ == "real") {
                  echo '              <td align="right">'. sprintf("%6.1f", $arr[$ix]);
              } elseif ($typ == "int") {
                  echo '              <td align="right">'. htmlspecialchars($arr[$ix]);
              } else {
                  echo $typ .':'. htmlspecialchars($arr[$ix]);
              }
              echo '</td>'."\n";
          }
          if ($total > 0) {
              echo '              <td>'. sprintf("%5.1f", $arr[0] * 100 / $total) .'%</td>'."\n";
          }
          echo '          </tr>'."\n";
      }
      if ($leftovers) {
          $ver = "Others";
          echo '          <tr>'."\n";
          echo '              <td><a href="/reports/systemstats.php?days='. $days .'&dig=%">'. htmlspecialchars($ver) .'</a></td>'."\n";
          echo '              <td>'. $leftovers .'</td>'."\n";
          echo '              <td>'. sprintf("%5.1f", $leftovers * 100 / $total) .'%</td>'."\n";
          echo '          </tr>'."\n";
      }
  }
  $to_days = 'TO_DAYS(updated) > TO_DAYS(NOW()) - '. $days;
  $q1 = mysql_query('SELECT COUNT(*), AVG(uptime), MAX(uptime), MAX(max_uptime) FROM automach WHERE '. $to_days);
  if ($q1 == 0) {
      print('MySQL error: '. mysql_errno() .':'. mysql_error());
      die('Query for count failed');
  }
  $tmp = mysql_fetch_row($q1);
  $total = $tmp[0];
?>
<p>
Information from <?php echo $total ?> machines.
<p>
<font size=7>Average uptime: <?php printf("%1.1f", $tmp[1]) ?> days</font>
<p>
Max uptime currently running: <?php printf("%1.1f", $tmp[2]) ?> days
<br>
Max uptime ever observed: <?php printf("%1.1f", $tmp[3]) ?> days
<table>
   <tr>
       <th>Count</th>
       <th align="left">Uptime</th>
   </tr>
   <tr>
       <td align="right"><?php echo dbcount('automach', $to_days .' AND uptime < 1'); ?></td>
       <td>0-1 days</td>
   </tr>
   <tr>
       <td align="right"><?php echo dbcount('automach', $to_days .' AND uptime < 10 AND uptime >= 1'); ?></td>
       <td>1-10 days</td>
   </tr>
   <tr>
       <td align="right"><?php echo dbcount('automach', $to_days .' AND uptime >= 10 AND uptime < 100'); ?></td>
       <td>10-100 days</td>
   </tr>
   <tr>
       <td align="right"><?php echo dbcount('automach', $to_days .' AND uptime >= 100'); ?></td>
       <td>More than 100 days</td>
   </tr>
</table>
<h2>Top ten long-running machines</h2>
<?php
  $query = mysql_query('SELECT uptime, kernel, cpu FROM automach WHERE '. $to_days .' ORDER BY uptime desc LIMIT 10');
  if ($query == 0) {
      print('MySQL error: '. mysql_errno() .':'. mysql_error());
      die('Query failed');
  }
?>
<table class="info">
   <tr>
       <td valign="top">
       <table border>
          <tr>
              <th>Uptime</th>
              <th>Kernel</th>
              <th>CPU</th>
          </tr>
<?php
  presentquery($query);
?>
       </table>
       </td>
   </tr>
</table>
<h2>Average uptime, by kernel</h2>
<?php
  $query = mysql_query('SELECT COUNT(*), SUBSTRING_INDEX(kernel, \'-\', 1) AS k, AVG(uptime), MAX(uptime) FROM automach WHERE '. $to_days .' GROUP BY k');
  if ($query == 0) {
      print('MySQL error: '. mysql_errno() .':'. mysql_error());
      die('Query failed');
  }
?>
<table class="info">
   <tr>
       <td valign="top">
       <table border>
          <tr>
              <th rowspan=2>Count</th>
              <th rowspan=2>Kernel</th>
              <th colspan=2>Uptime</th>
          </tr>
          <tr>
              <th>Typical</th>
              <th>Longest</th>
          </tr>
<?php
  presentquery($query, $total, 2);
?>
       </table>
       </td>
   </tr>
</table>
<p><strong>NOTE:</strong>
The Linux kernel (at least up to 2.4.2) has a flaw: It computes the result
of the "uptime" based on the internal "jiffies" counter, which counts the
time since boot, in units of 10 milliseconds.
<br>
This is typecast as an "unsigned long" - on the Intel boxes, that's an unsigned
32-bit number.
<br>
Well, it turns out that in a 32-bit number, you can store 497.1 days before the
number wraps. So all the numbers higher than this on this list are because:
<ul>
    <li>They are not Intel architectures
    <li>They have sent in updates on both sides of the wrap, and my scripts
    have successfully correlated them and concluded that it was a wrap, not
    a reboot.
</ul>
Thanks to Brian "Z" Frappier for alerting me to the problem!  
<?php pagebottom() ?>
</body>
